# Copyright (C) 2008, Mads D. Kristensen
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# This service stores a file in the storage area of the execution 
# environment.
#
# Args: 
# filename (str): The name of the file to store. [optional]
#                 If a filename is given the service tries
#                 to store the data under that name. If this
#                 is not possible an IOError is raised.
# data (str): The data that is written to the file. The file
#             is opened in binary mode when writing this data.
#
# Return: (str) The name of the file stored in the local filesystem.

from os.path import sep

def pick_random_filename():
    from uuid import uuid4
    from os import access, F_OK
    filename = uuid4().hex
    while access('see' + sep + 'storage' + sep + filename, F_OK):
        filename = uuid4().hex
    del access, F_OK, uuid4
    return filename

def perform(data, filename=None):
    # Check that the mandatory arguments are present.
    if filename and type(filename) != str:
        raise TypeError('"filename" argument must be of type str.')
    if type(data) != str:
        raise TypeError('"data" argument must be of type str.')
    
    # Set the file name.
    if not filename:
        filename = pick_random_filename()
    else:
        # Validate the filename.
        if '..' in filename or '~' in filename:
            raise IOError('Backtracking is not allowed.')
        # Check whether the file already exists. Overwriting is not allowed.
        from os import access, F_OK
        if access('see' + sep + 'storage' + sep + filename, F_OK):
            del access, F_OK
            raise IOError('Filename already in use.')
        del access, F_OK
    
    # Write the file.
    outfile = open('see' + sep + 'storage' + sep + filename, 'wb')
    outfile.write(data)
    outfile.close()
    
    # Return the file name to the caller.
    return filename
